<?php

namespace Push\Payloads;

use Push\Interfaces\PayloadInterface;

abstract class AbstractPayload implements PayloadInterface
{
    /**
     * @var string 消息类型
     */
    protected $category;

    /**
     * @var int 角标
     */
    protected $badge;

    /**
     * @var string 提示音
     */
    protected $sound;

    /**
     * @var array 需要发送的额外消息
     */
    protected $extraMessage;

    /**
     * @var string
     */
    protected $encodePayload;

    /**
     * @return string
     */
    public function payload()
    {
        if (!isset($this->encodePayload)) {
            $this->encodePayload = $this->refresh();
        }
        return $this->encodePayload;
    }

    /**
     * @param array|string $alert
     * @return array
     */
    protected function prepare($alert)
    {
        $payload = [];
        if (isset($this->category)) {
            $payload['aps']['category'] = $this->category;
        }
        if ($alert) {
            $payload['aps']['alert'] = $alert;
        }
        if (isset($this->badge)) {
            $payload['aps']['badge'] = $this->badge;
        }
        if (isset($this->sound)) {
            $payload['aps']['sound'] = $this->sound;
        }
        if ($this->extraMessage && is_array($this->extraMessage)) {
            foreach ($this->extraMessage as $key => $value) {
                if ($key !== 'aps') {
                    $payload[$key] = $value;
                }
            }
        }

        return $payload;
    }

    /**
     * @param $payload
     * @return string
     */
    protected function encode($payload)
    {
        return json_encode(
            $payload, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
    }

    /**
     * @return string
     */
    public function refresh()
    {
        $payload = $this->prepare($this->alert());
        return $this->encode($payload);
    }

    /**
     * @return array|string
     */
    abstract public function alert();

    /**
     * @return string
     */
    public function getCategory()
    {
        return $this->category;
    }

    /**
     * @param string $category
     */
    public function setCategory($category)
    {
        $this->category = $category;
    }

    /**
     * @return int
     */
    public function getBadge()
    {
        return $this->badge;
    }

    /**
     * @param int $badge
     */
    public function setBadge($badge)
    {
        $this->badge = $badge;
    }

    /**
     * @return string
     */
    public function getSound()
    {
        return $this->sound;
    }

    /**
     * @param string $sound
     */
    public function setSound($sound)
    {
        $this->sound = $sound;
    }

    /**
     * @return array
     */
    public function getExtraMessage()
    {
        return $this->extraMessage;
    }

    /**
     * @param array $extraMessage
     */
    public function setExtraMessage($extraMessage)
    {
        $this->extraMessage = $extraMessage;
    }
}
